package org.apache.dolphinscheduler.api.service.impl;

import org.apache.dolphinscheduler.api.enums.Status;
import org.apache.dolphinscheduler.api.service.ChargingRuleService;
import org.apache.dolphinscheduler.api.utils.Result;
import org.apache.dolphinscheduler.common.constants.Constants;
import org.apache.dolphinscheduler.dao.entity.ChargingRule;
import org.apache.dolphinscheduler.dao.mapper.ChargingRuleMapper;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;

/**
 * <p>
 * 收费规则表 服务实现类
 * </p>
 *
 * @author denggh
 * @since 2023-08-15
 */
@Service
public class ChargingRuleServiceImpl extends BaseServiceImpl implements ChargingRuleService {

    @Autowired
    private ChargingRuleMapper chargingRuleMapper;
    @Override
    public Result selectChargingRuleList() {
        Result result = new Result();
        LambdaQueryWrapper<ChargingRule> lqw = new LambdaQueryWrapper<>();
        List<ChargingRule> chargingRules = chargingRuleMapper.selectList(lqw);
        result.setData(chargingRules);
        putMsg(result, Status.SUCCESS);
        return result;
    }

    @Override
    public Map<String, Object> selectChargingRuleById(Long chargingRuleId) {
        Map<String, Object> result = new HashMap<>();
        ChargingRule chargingRule = chargingRuleMapper.selectById(chargingRuleId);
        if (chargingRule != null) {
            result.put(Constants.DATA_LIST, chargingRule);
            putMsg(result, Status.SUCCESS);
        }
        return result;
    }

    @Override
    public Map<String, Object> insertChargingRule(ChargingRule chargingRule) {
        Map<String, Object> result = new HashMap<>();
        int insert = chargingRuleMapper.insert(chargingRule);
        if (insert > 0) {
            result.put(Constants.DATA_LIST, chargingRule);
            putMsg(result, Status.SUCCESS);
        }
        return result;
    }

    @Override
    public Map<String, Object> updateChargingRule(List<ChargingRule> chargingRule) {
        Map<String, Object> result = new HashMap<>();

        if (chargingRule.size() > 1 && !judge(chargingRule)) {
            putMsg(result, Status.NOT_ALLOW_CHARGING_RULE);
            return result;
        }

        for (ChargingRule rule : chargingRule) {

            int update = chargingRuleMapper.updateById(rule);
            if (update > 0) {
                putMsg(result, Status.SUCCESS);
            }
        }
        return result;
    }

    @Override
    public Map<String, Object> deleteChargingRuleById(Long chargingRuleId) {
        Map<String, Object> result = new HashMap<>();
        int delete = chargingRuleMapper.deleteById(chargingRuleId);
        if (delete > 0) {
            putMsg(result, Status.SUCCESS);
        }
        return result;
    }

    public boolean judge(List<ChargingRule> chargingRule) {

        if (CollectionUtils.isEmpty(chargingRule)) {
            return false;
        }
        Integer max = chargingRule.stream().map(ChargingRule::getId).max(Integer::compare).get();
        for (int i = 0; i < chargingRule.size(); i++) {
            if (chargingRule.get(i).getMaxNumber().compareTo(BigDecimal.ZERO) < 0
                    && !chargingRule.get(i).getId().equals(max)) {
                // 只有最后一个梯度的最大值可以为0
                return false;
            }
            if (chargingRule.get(i).getMaxNumber().compareTo(BigDecimal.ZERO) > 0
                    && chargingRule.get(i).getMaxNumber().compareTo(chargingRule.get(i).getMinNumber()) <= 0) {
                // 一个梯度的最小值不能大于等于最大值
                return false;
            }
            if (i + 1 < chargingRule.size()) {
                double min1 = chargingRule.get(i).getMinNumber().doubleValue();
                double min2 = chargingRule.get(i + 1).getMinNumber().doubleValue();
                double max1 = chargingRule.get(i).getMaxNumber().doubleValue();
                double max2 = chargingRule.get(i + 1).getMaxNumber().doubleValue();
                if (max2 < 0) {
                    max2 = min2 + 1;
                }
                // 两个集合不允许存在交集 true 为有交集
                boolean b = Math.max(min1, min2) < Math.min(max1, max2);
                if (b) {
                    return false;
                }
            }
        }
        return true;
    }
}
